package ltd.newbee.mall.config;
import ltd.newbee.mall.config.constant.PreventDuplicateSubmit;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class PreventDuplicateSubmitAspect {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Around("@annotation(preventDuplicateSubmit)")
    public Object around(ProceedingJoinPoint joinPoint, PreventDuplicateSubmit preventDuplicateSubmit) throws Throwable {
        String lockKey = generateLockKey(joinPoint, preventDuplicateSubmit);

        // 尝试获取锁
        Boolean success = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", preventDuplicateSubmit.expire(), TimeUnit.SECONDS);

        if (Boolean.TRUE.equals(success)) {
            try {
                // 获取锁成功，执行方法
                return joinPoint.proceed();
            } finally {
                // 方法执行完成后删除锁（可选，根据业务需求）
                // redisTemplate.delete(lockKey);
            }
        } else {
            // 获取锁失败，表示重复提交
            throw new RuntimeException(preventDuplicateSubmit.message());
        }
    }

    private String generateLockKey(ProceedingJoinPoint joinPoint, PreventDuplicateSubmit preventDuplicateSubmit) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        String key = preventDuplicateSubmit.key();
        if (!StringUtils.hasText(key)) {
            // 如果未指定key，使用类名+方法名作为默认key
            key = method.getDeclaringClass().getName() + "." + method.getName();
        }

        // 可以添加用户ID等参数来区分不同用户的请求
        // 这里简单实现，实际项目中可能需要更复杂的key生成逻辑
        return "prevent_duplicate:" + key;
    }
}
